package com.yao.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.stream.CollectorUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yao.system.entity.*;
import com.yao.system.entity.dto.UserDTO;
import com.yao.system.entity.vo.ResumeAdminVO;
import com.yao.system.entity.vo.ResumeVO;
import com.yao.system.mapper.ResumeMapper;
import com.yao.system.service.IJobResumeService;
import com.yao.system.service.IJobService;
import com.yao.system.service.IResumeService;
import com.yao.system.service.IUserService;
import com.yao.system.util.UserContext;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class ResumeServiceImpl extends ServiceImpl<ResumeMapper, Resume> implements IResumeService {

    private final IJobResumeService jobResumeService;
    private final IJobService jobService;
    private final IUserService userService;
    private final ThreadPoolExecutor coreThreadPool;

    @Override
    public Result addResume(Resume resume) {
        UserDTO user = UserContext.getUser();
        resume.setUserId(user.getId());
        resume.setUserName(user.getName());
        if (resume.getId() == null) {
            save(resume);
            System.out.println("========添加========");
            return Result.ok("添加成功");
        }
        boolean update = updateById(resume);
        if (!update)
            return Result.error("修改失败");
        System.out.println("========修改========");
        return Result.ok("修改成功");
    }

    @Override
    public Result getList() {
        Long id = UserContext.getUser().getId();
        List<Resume> list = lambdaQuery().eq(Resume::getUserId, id).list();
        return Result.ok(list);
    }

    /**
     * 查询企业已收到的简历列表
     */
    @Override
    public Result getReceiveResumeList(Integer page, Integer size) {
        Long id = UserContext.getUser().getId();
        Page<JobResume> jobResumePage = jobResumeService.lambdaQuery()
                .eq(JobResume::getJobUserId, id)
                .orderByDesc(JobResume::getUpdateTime)
                .page(Page.of(page, size));

        List<JobResume> list = jobResumePage.getRecords();
        int pages = (int) jobResumePage.getPages();
        int total = (int) jobResumePage.getTotal();

        if (CollectionUtil.isEmpty(list)) {
            return Result.ok(PageResult.of(total, pages, null));
        }

        Set<Long> resumeIds = new HashSet<>();
        Set<Long> jobIds = new HashSet<>();
        Set<Long> userIds = new HashSet<>();
        for (JobResume jobResume : list) {
            userIds.add(jobResume.getResumeUserId());
            resumeIds.add(jobResume.getResumeId());
            jobIds.add(jobResume.getJobId());
        }

        CompletableFuture<Map<Long, Job>> jobFuture = CompletableFuture.supplyAsync(() -> {
            return jobService.getByIds(jobIds);
        }, coreThreadPool);
        CompletableFuture<Map<Long, User>> userFuture = CompletableFuture.supplyAsync(() -> {
            return userService.getByIds(userIds);
        }, coreThreadPool);

        Map<Long, Job> jobMap = jobFuture.join();
        Map<Long, User> userMap = userFuture.join();

        List<Resume> resumeList = lambdaQuery()
                .in(Resume::getId, resumeIds)
                .list();

        Map<Long, Resume> resumeMap = resumeList.stream()
                .collect(Collectors.toMap(Resume::getId, resume -> resume));

        List<ResumeVO> voList = new ArrayList<>();
        for (JobResume jobResume : list) {
            ResumeVO vo = new ResumeVO();
            Resume resume = resumeMap.get(jobResume.getResumeId());
            User user = userMap.get(jobResume.getResumeUserId());
            BeanUtil.copyProperties(resume, vo);
            vo.setJobId(jobResume.getJobId());
            vo.setImage(user.getImage());
            //这里以后可以优化一下，在循环里查数据库 性能太差了 --- (2024-4-17 霖) --- 已优化 来自 5分钟后
            //Job job = jobService.getById(jobResume.getJobId());
            Job job = jobMap.get(jobResume.getJobId());
            if (job != null) {
                vo.setTitle(job.getTitle());
            }
            //if (job == null) continue;
            voList.add(vo);
        }
        return Result.ok(PageResult.of(total, pages, voList));
    }


    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime time = LocalDateTime.of(now.getYear(),
                now.getMonth(),
                now.getDayOfMonth(), 0, 0, 0);
        System.out.println(now);
        System.out.println(time);
    }

    /**
     * 查询企业今日收到的简历列表
     *
     * @return
     */
    @Override
    public Result queryReceiveResumeListByDay() {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime time = LocalDateTime.of(now.getYear(),
                now.getMonth(),
                now.getDayOfMonth(), 0, 0, 0);
        List<JobResume> list = jobResumeService.lambdaQuery()
                .eq(JobResume::getJobUserId, UserContext.getUser().getId())
                .ge(JobResume::getCreateTime, time)
                .le(JobResume::getCreateTime, now)
                .list();
        if (CollectionUtil.isEmpty(list)) {
            return Result.ok(Collections.emptyList());
        }

        Set<Long> resumeIds = new HashSet<>();
        Set<Long> jobIds = new HashSet<>();
        Set<Long> userIds = new HashSet<>();
        for (JobResume jobResume : list) {
            userIds.add(jobResume.getResumeUserId());
            resumeIds.add(jobResume.getResumeId());
            jobIds.add(jobResume.getJobId());
        }

        CompletableFuture<Map<Long, Job>> jobFuture = CompletableFuture.supplyAsync(() -> {
            return jobService.getByIds(jobIds);
        }, coreThreadPool);
        CompletableFuture<Map<Long, User>> userFuture = CompletableFuture.supplyAsync(() -> {
            return userService.getByIds(userIds);
        }, coreThreadPool);

        Map<Long, Job> jobMap = jobFuture.join();
        Map<Long, User> userMap = userFuture.join();

        List<Resume> resumeList = lambdaQuery()
                .in(Resume::getId, resumeIds)
                .list();

        Map<Long, Resume> resumeMap = resumeList.stream()
                .collect(Collectors.toMap(Resume::getId, resume -> resume));

        List<ResumeVO> voList = new ArrayList<>();
        for (JobResume jobResume : list) {
            ResumeVO vo = new ResumeVO();
            Resume resume = resumeMap.get(jobResume.getResumeId());
            User user = userMap.get(jobResume.getResumeUserId());
            BeanUtil.copyProperties(resume, vo);
            vo.setJobId(jobResume.getJobId());
            vo.setImage(user.getImage());
            Job job = jobMap.get(jobResume.getJobId());
            if (job != null) {
                vo.setTitle(job.getTitle());
            }
            voList.add(vo);
        }

        return Result.ok(voList);
    }

    /**
     * 普通用户更新或新增个人简历
     *
     * @param resume
     * @return
     */
    @Override
    public Result updateResume(Resume resume) {
        UserDTO user = UserContext.getUser();
        Resume one = lambdaQuery()
                .eq(Resume::getUserId, user.getId())
                .one();
        if (one == null) {
            resume.setUserId(user.getId());
            resume.setUserName(user.getName());
            save(resume);
            return Result.ok("新增简历成功");
        }
        boolean flag = this.updateById(resume);
        if (!flag)
            return Result.error("修改失败");
        return Result.ok("修改成功");
    }

    @Override
    public Map<Long, Resume> getByIds(Set<Long> userIds) {
        List<Resume> resumeList = lambdaQuery()
                .in(Resume::getUserId, userIds)
                .list();
        Map<Long, Resume> resumeMap = resumeList.stream()
                .collect(Collectors.toMap(Resume::getUserId, resume -> resume));
        return resumeMap;
    }

    /**
     * 查询个人简历
     *
     * @return
     */
    @Override
    public Result getMyResume() {
        Resume resume = lambdaQuery()
                .eq(Resume::getUserId, UserContext.getUser().getId())
                .one();
        if (resume == null) {
            return Result.ok(null, "");
        }
        resume.setCreateTime(null);
        resume.setUpdateTime(null);
        return Result.ok(resume);
    }

    /**
     * 根据id 查询企业收到的简历详情
     *
     * @param id
     * @return
     */
    @Override
    public Result getReceiveResume(Long id) {
        Resume resume = lambdaQuery()
                .eq(Resume::getId, id)
                .one();
        if (resume == null) {
            return Result.ok(null, "");
        }
        resume.setCreateTime(null);
        resume.setUpdateTime(null);
        return Result.ok(resume);
    }

    @Override
    public Result sendResume(JobResume jobResume) {
        UserDTO user = UserContext.getUser();
        List<Resume> list = lambdaQuery().eq(Resume::getUserId, user.getId()).list();
        if (list == null || list.size() == 0) {
            return Result.error("投递失败,暂无简历");
        }
        JobResume one = jobResumeService.lambdaQuery()
                .eq(JobResume::getJobId, jobResume.getJobId())
                .eq(JobResume::getResumeUserId, user.getId())
                .one();
        if (one != null) {
            return Result.error("已向该岗位投递过简历");
        }
        Resume resume = list.get(0);
        jobResume.setResumeId(resume.getId());
        jobResume.setResumeUserId(user.getId());
        boolean save = jobResumeService.save(jobResume);
        if (!save)
            return Result.error("投递失败");
        return Result.ok(null, "投递简历成功");
    }

    @Override
    public Result getSendJobList() {
        UserDTO user = UserContext.getUser();

        List<JobResume> jobResumeList = jobResumeService.lambdaQuery()
                .eq(JobResume::getResumeUserId, user.getId())
                .list();
        List<Long> collect = jobResumeList.stream().map(jobResume -> {
            return jobResume.getJobId();
        }).collect(Collectors.toList());

        List<Job> list = jobService.lambdaQuery().in(Job::getId, collect).list();

        return Result.ok(list);
    }


    @Override
    public Result queryResumeList(Integer page, Integer size) {
        Page<Resume> resumePage = lambdaQuery()
                .page(Page.of(page, size));
        List<Resume> resumeList = resumePage.getRecords();
        int total = (int) resumePage.getTotal();
        int pages = (int) resumePage.getPages();
        if (CollectionUtil.isEmpty(resumeList)) {
            Result.ok(PageResult.of(total, pages, null));
        }

        Set<Long> userIds = new HashSet<>();
        for (Resume resume : resumeList) {
            userIds.add(resume.getUserId());
        }

        CompletableFuture<Map<Long, User>> userFuture = CompletableFuture.supplyAsync(() -> {
            return userService.getByIds(userIds);
        }, coreThreadPool);

        Map<Long, User> userMap = userFuture.join();

        List<ResumeAdminVO> voList = new ArrayList<>();
        for (Resume resume : resumeList) {
            ResumeAdminVO vo = new ResumeAdminVO();
            User user = userMap.get(resume.getUserId());
            BeanUtil.copyProperties(resume, vo);
            if (user != null) {
                vo.setImage(user.getImage());
            }
            voList.add(vo);
        }

        return Result.ok(PageResult.of(total, pages, voList));
    }

    @Override
    public Result updateResumeAdmin(Resume resume) {
        updateById(resume);
        return Result.ok("修改成功");
    }


}
